package jlib.component.list
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	
	import jlib.component.core.Border;
	import jlib.component.layout.Layout;
	import jlib.component.layout.LayoutDirection;
	import jlib.component.layout.LinearLayout;
	import jlib.component.scroll.ScrollBarDirection;
	import jlib.core.JCore;
	
	public class ListBox extends Sprite {
		
		private var m_layout:Layout;
		private var m_selectedItem:AbstractItem;
		private var m_view:Rectangle;
		private var m_bAutoSize:Boolean;
		private var m_border:Border;
		
		public function ListBox() {
			super();
			buildDefault();
		}
		
		private function buildDefault(): void {
			m_layout = new LinearLayout;
			m_layout.setDirection(LayoutDirection.VERTICAL);
			m_border = new Border(1,0xcccccc,0,'solid','inner');
			setView(new Rectangle(0,0,100,100));
			addChild(m_layout);
			addChild(m_border);
		}
		
		public function getView(): Rectangle { return m_view.clone(); }
		/**
		 * ListBox의 보이는 영역을 설정합니다. 
		 * @param $view
		 */		
		public function setView($view:Rectangle): void {
			m_view = $view;
			update();
		}
		
		JCore function getLayout():Layout { return m_layout; }
		
		/**
		 * 선택 된 리스트의 인덱스를 반환합니다.
		 * @return index
		 */		
		public function getSelectedIndex(): int { return getItemIndex(getSelectedItem()); }
		/**
		 * 선택 된 리스트를 반환합니다. 
		 * @return listbox 객체
		 */		
		public function getSelectedItem(): AbstractItem { return m_selectedItem; }
		/**
		 * 리스트 정렬 방향을 설정합니다.
		 * @param $direction LayoutDirection
		 */		
		public function setDirection($direction:String): void {
			m_layout.setDirection($direction);
			update();
		}
		/**
		 * 리스트간의 간격을 설정합니다.
		 * @param $space px 값
		 */		
		public function setSpace($space:Number): void {
			m_layout.setSpace($space);
			update();
		}
		
		/**
		 * index 로 선택을 합니다.
		 * @param index 리스트 인덱스
		 * @param $useDispatch 이벤트 디스페치 유무
		 */		
		public function selectAt(index:int, $useDispatch:Boolean=true): void {
			var item:AbstractItem = getItemAt(index) as AbstractItem;
			updateSelectedList(item);
			if($useDispatch) dispatchSelectEvent();
		}
		
		/**
		 * @see com.aitmedia.component.core.Border
		 */		
		public function setBorder($thickness:int=0, $color:uint=0x000000, $type:String='solid', $position:String='middle'): void {
			m_border.setThickness($thickness), m_border.setColor($color), m_border.setType($type), m_border.setPosition($position);
			update();
		}
		
		/**
		 * 리스트 아이템을 추가합니다. 
		 * @param list AbstractListItem 객체.
		 */		
		public function addItem(list:AbstractItem): void {
			list.addEventListener(MouseEvent.CLICK, onClickItem );
			m_layout.addChild(list);
			update();
		}
		
		/**
		 * 리스트 아이템을 제거합니다. 
		 * @param list AbstractListItem 객체.
		 */		
		public function removeItem(list:AbstractItem): void {
			list.removeEventListener(MouseEvent.CLICK, onClickItem );
			m_layout.removeChild(list);
			update();
		}
		/**
		 * 리스트의 아이템들을 모두 제거합니다. 
		 */		
		public function removeAll(): void  {
			var len:int = getLength();
			for(var i:int=0;i<len;i++){
				removeItem(getItemAt(0));
			}
		}
		/**
		 * item의 index를 반환합니다.
		 * @param list AbstractListItem 객체
		 * @return int
		 */		
		public function getItemIndex(list:AbstractItem): int  { return m_layout.getChildIndex(list); }
		/**
		 * 리스트의 아이템 갯수를 반환합니다.
		 * @return int
		 */		
		public function getLength(): int { return m_layout.numChildren; }
		/**
		 * 리스트의 인덱스로 아이템을 가져옵니다.
		 * @param index 
		 * @return AbstractListItem 객체
		 */		
		public function getItemAt(index:int): AbstractItem { return m_layout.getChildAt(index) as AbstractItem; }
		/**
		 * 모든 정보를 업데이트 합니다. 
		 */		
		public function update(): void {
			m_border.width = m_view.width;
			m_border.height = m_view.height;
			m_layout.update();
			this.scrollRect = m_view;
		}
		
		private function dispatchSelectEvent(): void  { this.dispatchEvent(new Event(Event.SELECT)); }
		
		private function updateSelectedList($selectedList:AbstractItem): void {
			var item:AbstractItem;
			m_selectedItem = $selectedList;
			for(var i:int=0;i<m_layout.numChildren;i++){
				item = m_layout.getChildAt(i) as AbstractItem;
				item.deselect();
			}
			m_selectedItem.select();
		}
		
		private function onClickItem(e:Event): void {
			updateSelectedList(e.currentTarget as AbstractItem);
			dispatchSelectEvent();
		}
	}//c
}